package com.lyy.config;


import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;

import java.time.Duration;

/**
 * @author Liangyaoyun
 */
@EnableCaching
@Configuration
public class SpringCacheConfig {
    /** 缓存有效期，单位分钟 */
    private static final long TTL = 30L;

    @Autowired
    private RedisConnectionFactory connectionFactory;

    @Bean
    public CacheManager cacheManager() {

        // 使用Jackson来序列化和反序列化缓存值，默认使用JDK的序列化方式（中文有乱码）
        Jackson2JsonRedisSerializer<Object> serializer = new Jackson2JsonRedisSerializer<>(Object.class);
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);

        // 此项用于规避Java类嵌套时爆发的，LinkedHashMap类相关的类转换异常
        objectMapper.activateDefaultTyping(objectMapper.getPolymorphicTypeValidator(),
                ObjectMapper.DefaultTyping.NON_FINAL,
                JsonTypeInfo.As.PROPERTY);
        serializer.setObjectMapper(objectMapper);

        // 配置redis缓存管理对象: 设置缓存过期时间，序列化方式和Null值处理方案
        RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
                // 设置缓存有效期
                .entryTtl(Duration.ofMinutes(TTL))
                .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(serializer))
                .disableCachingNullValues();

        // 返回Cache管理器
        return RedisCacheManager.builder(connectionFactory).cacheDefaults(config).build();
    }
}
